import * as step from '@ali/flow-step-toolkit'
import * as sinon from 'sinon';
import * as path from 'path';
import {expect} from 'chai';

const proxyquire = require('proxyquire');

describe('setup', () => {
    let sandbox: sinon.SinonSandbox;
    let stepExportEnvVarStub: sinon.SinonStub;
    let getNewCustomMavenSettingCertificateStub: sinon.SinonStub;
    let getNewMavenPrivateRepoCertificateStub: sinon.SinonStub;

    const fsStub = {
        dirname: sinon.stub(),
        mkdirSync: sinon.stub(),
        writeFileSync: sinon.stub()
    };
    const {setup} = proxyquire('../src/setup', {
        fs: fsStub
    })

    beforeEach(() => {
        sandbox = sinon.createSandbox();
        stepExportEnvVarStub = sandbox.stub(step, 'exportEnvVar');

        getNewCustomMavenSettingCertificateStub = sandbox.stub(step.certificate, 'getNewCustomMavenSettingCertificate');
        getNewMavenPrivateRepoCertificateStub = sandbox.stub(step.certificate, 'getNewMavenPrivateRepoCertificate');
    });

    afterEach(() => {
        sandbox.restore();
    });

    it('should create the directory and write custom maven settings to the file', async () => {
        const flowJobToken = 'some-token';
        const mavenSettingXmlPath = '/path/to/maven/settings.xml';
        const customMavenSettingCertificate = {
            mavenSettingsContent: '<xml>custom</xml>',
        };

        getNewCustomMavenSettingCertificateStub.resolves(customMavenSettingCertificate);

        await setup(flowJobToken, mavenSettingXmlPath);

        sinon.assert.calledWith(stepExportEnvVarStub, 'MAVEN_SETTING_XML_PATH');
        sinon.assert.calledWith(fsStub.mkdirSync, path.dirname(mavenSettingXmlPath), {recursive: true});
        sinon.assert.calledWith(fsStub.writeFileSync, mavenSettingXmlPath, customMavenSettingCertificate.mavenSettingsContent);
    });

    it('should create the directory and write maven private repo settings to the file', async () => {
        const flowJobToken = 'some-token';
        const mavenSettingXmlPath = '/path/to/maven/settings.xml';
        const mavenPrivateRepoCertificate = {
            mavenSettingsContent: '<xml>private</xml>',
        };

        getNewCustomMavenSettingCertificateStub.resolves(undefined);
        getNewMavenPrivateRepoCertificateStub.resolves(mavenPrivateRepoCertificate);

        await setup(flowJobToken, mavenSettingXmlPath);

        sinon.assert.calledWith(stepExportEnvVarStub, 'MAVEN_SETTING_XML_PATH');
        sinon.assert.calledWith(fsStub.mkdirSync, path.dirname(mavenSettingXmlPath), {recursive: true});
        sinon.assert.calledWith(fsStub.writeFileSync, mavenSettingXmlPath, mavenPrivateRepoCertificate.mavenSettingsContent);
    });

    it('should throw an error if maven private repo settings are empty', async () => {
        const flowJobToken = 'some-token';
        const mavenSettingXmlPath = '/path/to/maven/settings.xml';

        getNewCustomMavenSettingCertificateStub.resolves(undefined);
        getNewMavenPrivateRepoCertificateStub.resolves(undefined);

        try {
            await setup(flowJobToken, mavenSettingXmlPath);
            // never reached
            expect(1).to.be.equal(0);
        } catch (error) {
            // @ts-ignore
            expect(error.message).to.be.equal('maven private repo settings is empty');
        }
    });

    it('should throw an error if maven private repo settings are blank', async () => {
        const flowJobToken = 'some-token';
        const mavenSettingXmlPath = '/path/to/maven/settings.xml';
        const mavenPrivateRepoCertificate = {
            mavenSettingsContent: '',
        };

        getNewCustomMavenSettingCertificateStub.resolves(undefined);
        getNewMavenPrivateRepoCertificateStub.resolves(mavenPrivateRepoCertificate);

        try {
            await setup(flowJobToken, mavenSettingXmlPath);
            // never reached
            expect(1).to.be.equal(0);
        } catch (error) {
            // @ts-ignore
            expect(error.message).to.be.equal('maven private repo settings is empty');
        }
    });

    it('should throw an error if maven private repo settings is null', async () => {
        const flowJobToken = 'some-token';
        const mavenSettingXmlPath = '/path/to/maven/settings.xml';
        const mavenPrivateRepoCertificate = {
            mavenSettingsContent: null,
        };

        getNewCustomMavenSettingCertificateStub.resolves(undefined);
        getNewMavenPrivateRepoCertificateStub.resolves(mavenPrivateRepoCertificate);

        try {
            await setup(flowJobToken, mavenSettingXmlPath);
            // never reached
            expect(1).to.be.equal(0);
        } catch (error) {
            // @ts-ignore
            expect(error.message).to.be.equal('maven private repo settings is empty');
        }
    });
})